package org.oos.model;

import static org.oos.Constants.SPACED_COMMA;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.oos.OOS4Java;
import org.oos.atom.elements.Author;
import org.oos.atom.elements.Category;
import org.oos.atom.elements.Link;
import org.oos.atom.elements.Rating;
import org.oos.atom.elements.Text;
import org.oos.atom.entries.MultimediaEntry;
import org.oos.atom.entries.ReviewEntry;
import org.oos.atom.entries.impl.ReviewEntryImpl;
import org.oos.auth.UserPrivacyType;
import org.oos.dao.MultimediaDao;
import org.oos.dao.UserSiteDao;
import org.oos.dao.exceptions.DeleteException;
import org.oos.dao.exceptions.ReadException;
import org.oos.dao.exceptions.UpdateException;
import org.oos.lists.MultimediaList;

/**
 * Describes the structure of the review which can be assigned to a Site by a
 * User.
 * 
 * @author pablo.gonzalez@11870.com
 * 
 */
public class Review extends AbstractEntityImpl {
	private static final long serialVersionUID = 2707984152750120221L;

	private ReviewEntry entry;
	private Site site;
	private MultimediaList multimedias;
	
	public static final String ID = "REVIEW";

	public Review(OOS4Java oos4Java) {
		super(oos4Java);
		this.entry = new ReviewEntryImpl();
	}

	public Review(OOS4Java oos4Java, ReviewEntry entry) {
		super(oos4Java);
		this.entry = entry;
		this.site = new Site(oos4Java, entry);
	}

	public Review(OOS4Java oos4Java, User user, Site site) {
		super(oos4Java);
		this.entry = new ReviewEntryImpl();
		this.entry.setOosId(site.getOosId());
		this.entry.setSlug(site.getSlug());
		this.setSite(site);
		this.setAuthor(user);
	}

	public ReviewEntry getEntry() {
		return entry;
	}

	public void setEntry(ReviewEntry entry) {
		this.entry = entry;
	}

	public Site getSite() {
		return site;
	}

	public void setSite(Site site) {
		this.site = site;
		this.entry.setOosId(site.getOosId());
		this.entry.setSlug(site.getSlug());
		this.entry.setTitle(new Text(site.getName()));
		this.entry.setPhone(site.getPhone());
		this.entry.setUrl(site.getUrl());
		try {
			this.entry.setLocation(site.getLocation().clone());
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

	public Author getAuthor() {
		return entry.getAuthor();
	}

	public void setAuthor(Author author) {
		entry.setAuthor(author);
	}

	public UserAvatar getAuthorAvatar() {
		return entry.getAuthor().getAvatar();
	}

	public String getTitle() {
		if (entry.getSummary() != null && entry.getSummary().hasValue()) {
			return entry.getSummary().getValue();
		}
		return null;
	}

	public void setTitle(String title) {
		Text text = new Text(title);
		entry.setSummary(text);
	}

	public String getContent() {
		if (entry.getContent() != null && entry.getContent().hasValue()) {
			return entry.getContent().getValue();
		}
		return null;
	}

	public void setContent(String content) {
		Text text = new Text(content);
		entry.setContent(text);
	}

	public Date getDate() {
		return entry.getDate();
	}

	public Integer getRating() {
		return entry.getRating() != null ? entry.getRating().getValue() : 0;
	}

	public void setRating(Rating rating) {
		entry.setRating(rating);
	}

	public Integer getRatingValue() {
		if (entry.getRating() != null) {
			return entry.getRating().getValue();
		} else {
			return 0;
		}
	}

	public void setRatingValue(Integer value) {
		Rating rating = new Rating();
		rating.setValue(value);
		entry.setRating(rating);
	}

	public String getLanguage() {
		if (entry.getContent() != null) {
			return entry.getContent().getLanguage();
		}
		return null;
	}

	public List<Link> getLinks() {
		return entry.getLinks();
	}

	public List<String> getTags() {
		List<String> tags = new ArrayList<String>();
		for (Category category : entry.getTags()) {
			tags.add(category.getTerm());
		}
		return tags;
	}

	public CharSequence getTagsText() {
		StringBuffer buffer = new StringBuffer();
		for (String tag : getTags()) {
			buffer.append(tag).append(SPACED_COMMA);
		}
		if (buffer.length() > 0) {
			return buffer.substring(0, buffer.length() - 2);
		} else {
			return "";
		}
	}

	public void setTags(List<String> tags) {
		if (tags != null) {
			List<Category> categories = new ArrayList<Category>();
			for (String tag : tags) {
				Category category = Category.create(Category.Type.TAGS,
						getAuthor().getSlug());
				category.setTerm(tag);
				categories.add(category);
			}
			entry.setTags(categories);
		}
	}

	public void addTag(String tag) {
		Category category = Category.create(Category.Type.TAGS, getAuthor()
				.getSlug());
		category.setTerm(tag);
		entry.addTag(category);
	}

	public List<String> getLists() {
		List<String> lists = new ArrayList<String>();
		for (Category category : entry.getLists()) {
			lists.add(category.getTerm());
		}
		return lists;
	}

	public CharSequence getListsText() {
		StringBuffer buffer = new StringBuffer();
		for (String tag : getLists()) {
			buffer.append(tag).append(SPACED_COMMA);
		}
		if (buffer.length() > 0) {
			return buffer.substring(0, buffer.length() - 2);
		} else {
			return "";
		}
	}

	public void setLists(List<String> lists) {
		if (lists != null) {
			List<Category> categories = new ArrayList<Category>();
			for (String list : lists) {
				Category category = Category.create(Category.Type.LISTS,
						getAuthor().getSlug());
				category.setTerm(list);
				categories.add(category);
			}
			entry.setLists(categories);
		}
	}

	public void addList(String list) {
		Category category = Category.create(Category.Type.LISTS, getAuthor()
				.getSlug());
		category.setTerm(list);
		entry.addList(category);
	}

	public UserPrivacyType getPrivacy() {
		Category category = entry.getPrivacy();
		if (category != null) {
			return UserPrivacyType.resolve(category.getTerm());
		} else {
			return UserPrivacyType.PUBLIC;
		}
	}

	public void setPrivacy(UserPrivacyType privacy) {
		Category category = Category.create(Category.Type.PRIVACY);
		category.setTerm(privacy.toString().toLowerCase());
		entry.setPrivacy(category);
	}

	public void update() throws UpdateException {
		UserSiteDao dao = oos4Java.getUserSiteDao();
		dao.setUserSlug(getAuthor().getSlug());
		dao.update(entry);
	}

	public void delete() throws DeleteException {
		UserSiteDao dao = oos4Java.getUserSiteDao();
		dao.setUserSlug(getAuthor().getSlug());
		dao.delete(entry);
	}

	public void update(Review review) {
		this.entry = review.entry;
		this.multimedias = review.multimedias;
	}

	public MultimediaList getMultimedia() throws ReadException {
		if (getAuthor().getSlug() == null) {
			return new MultimediaList(oos4Java,
					new ArrayList<MultimediaEntry>(), this);
		}

		MultimediaDao dao = oos4Java.getMultimediaDao();
		dao.setUserSlug(getAuthor().getSlug());
		dao.setSiteSlug(getSite().getSlug());
		multimedias = new MultimediaList(oos4Java, dao.read(), this);

		return multimedias;
	}

	public void addMultimedia(File file, String description, String contentType)
			throws ReadException {
		getMultimedia().add(file, description, contentType);
	}

	public void addMultimedia(File file, String contentType)
			throws ReadException {
		getMultimedia().add(file, contentType);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Review) {
			Review other = (Review) obj;
			return (other.getSite().getSlug().equals(getSite().getSlug()) || other
					.getSite().getOosId().equals(getSite().getOosId()))
					&& other.getAuthor().getSlug()
							.equals(getAuthor().getSlug());
		}
		return false;
	}
	
	@Override
	public String toString() {
		return getSite().getName();
	}
}
